#include <stdio.h>
#include <unistd.h>

#include <atomic>
#include <thread>

int sum = 0;
std::atomic<int> sum11(0);

void add() {
  for (int i = 0; i < 1000000; ++i) {
    sum++;  // sum = sum + 1; 先读后写 两步操作 不能保证原子性
  }
}
int test_add() {
  sum = 0;
  std::thread thr1(add);
  std::thread thr2(add);
  std::thread thr3(add);
  std::thread thr4(add);
  thr1.join();
  thr2.join();
  thr3.join();
  thr4.join();
  printf("%d\n", sum);
}

void atom_add() {
  for (int i = 0; i < 1000000; ++i) {
    sum11++;  // std::atomic<T>保证原子性
    // std::atomic_fetch_add(&sum11, 1);
  }
}
int test_atom_add() {
  sum11 = 0;
  std::thread thr1(atom_add);
  std::thread thr2(atom_add);
  std::thread thr3(atom_add);
  std::thread thr4(atom_add);
  thr1.join();
  thr2.join();
  thr3.join();
  thr4.join();
  printf("%d\n", (int)sum11);
}

void addc() {
  for (int i = 0; i < 1000000; ++i) {
    int old = sum;
    while (!__sync_bool_compare_and_swap(&sum, old, old + 1)) {
      old = sum;  // 自旋
    }
  }
}
int test_addc() {
  sum = 0;
  std::thread thr1(addc);
  std::thread thr2(addc);
  std::thread thr3(addc);
  std::thread thr4(addc);
  thr1.join();
  thr2.join();
  thr3.join();
  thr4.join();
  printf("%d\n", sum);
}

void add11() {
  for (int i = 0; i < 1000000; ++i) {
    int old = sum11;
    while (!std::atomic_compare_exchange_weak(&sum11, &old, old + 1)) {
      // old = sum11;  // 已自旋
    }
  }
}
int test_add11() {
  sum11 = 0;
  std::thread thr1(add11);
  std::thread thr2(add11);
  std::thread thr3(add11);
  std::thread thr4(add11);
  thr1.join();
  thr2.join();
  thr3.join();
  thr4.join();
  printf("%d\n", (int)sum11);
}

int main() {
  test_add();
  test_atom_add();
  test_addc();
  test_add11();
}